#include "common.hpp"

void usage(string name){
	cout << "Usage: " << endl;
	cout << "       " << "-d: video device path, necessary" << endl;
	cout << "       " << "-w: width" << endl;
	cout << "       " << "-h: height" << endl;
	cout << "       " << "-f: format" << endl;
	cout << "       " << "-p: Camera info" << endl;
	cout << "       " << "-P: Camera info full" << endl;
	cout << "       " << "-D: Enable debug" << endl;
	cout << endl;
	cout << "Examples:" << endl;
	cout << "       " << name << " -d /dev/video11 => Auto to set width/height/fmt" << endl;
	cout << "       " << name << " -d /dev/video11 -w 1920 -h 1080 -f NV12 => Manual to set width/height/fmt" << endl;
	cout << "       " << name << " -d /dev/video11 -p => Printf Camera info" << endl;
	cout << "       " << name << " -d /dev/video11 -P => Printf Camera all info" << endl;
	cout << endl;
	cout << "Format Suport List:" << endl;
	cout << "       " << " NV12" << endl;
	cout << "       " << " NV21" << endl;
	cout << "       " << " RGB3" << endl;
	cout << "       " << " BGR3" << endl;
}

int main(int argc,char ** argv){
	string _FMT;
	string RGA_FMT;
	string DEVICE;
	ManV4L2 * v4l2 = NULL;
	int ret = 0;
	int o = 0;
	int printinfo = 0;
	if(argc == 1) {
		usage(argv[0]);
		return 0;
	}

	while ((o = getopt(argc,argv,"d:w:h:f:pPD")) != -1){
		switch(o) {
			case 'p':
				printinfo = 1;
				break;
			case 'P':
				printinfo = 2;
				break;
			case 'f':
				_FMT = optarg;
				break;
			case 'w':
				WIDTH = atoi(optarg);
				break;
			case 'h':
				HEIGHT = atoi(optarg);
				break;
			case 'd':
				DEVICE = optarg;
				break;
			case 'D':
				MAN_DEBUG_CAP = true;
				break;

			default:
				usage(argv[0]);
				return -1;
		}
	}

	v4l2 = new ManV4L2(DEVICE);
	if(v4l2->init()){
		usage(argv[0]);
		delete v4l2;
		return -1;
	}

	if(printinfo != 0){
		if(printinfo == 1){
			v4l2->printCameraInfo();

		} else if(printinfo == 2) {
			v4l2->printCameraInfo();
			cout << endl;
			cout << endl;
			v4l2->getFmtSupport();
		}
		delete v4l2;
		return 0;
	}

	if (!WIDTH || !HEIGHT || !_FMT.length()) {
		if(v4l2->setFmt())
			return -1;
		else {
			int i = 0;
			int flag = false;
			WIDTH = v4l2->fmt.fmt.pix.width;
			HEIGHT = v4l2->fmt.fmt.pix.height;
			for(i = 0; i < sizeof(man_pixfmt) / sizeof(man_pixfmt[0]); i++){
				if(v4l2->fmt.fmt.pix.pixelformat == man_pixfmt[i].v4l2_fmt){
				       _FMT = man_pixfmt[i].name;
				       FMT = man_pixfmt[i].rga_fmt;
				       RGA_FMT = man_pixfmt[i].rga_fmt_name;
				       flag = true;
				       break;	
				}
			}
			if(flag == false){
				delete v4l2;
				cout << "Set FMT auto fail!" << _FMT << endl;
				return -1;
			}
		}
	} else {
		int i = 0;
		int flag = false;
		for(i = 0; i < sizeof(man_pixfmt) / sizeof(man_pixfmt[0]); i++){
			if(!_FMT.compare(man_pixfmt[i].name)){
				FMT = man_pixfmt[i].rga_fmt;
				RGA_FMT = man_pixfmt[i].rga_fmt_name;
				if(!v4l2->setFmt(_FMT,WIDTH,HEIGHT))
					flag = true;
				if(v4l2->fmt.fmt.pix.width != WIDTH || v4l2->fmt.fmt.pix.height != HEIGHT || man_pixfmt[i].v4l2_fmt != v4l2->fmt.fmt.pix.pixelformat)
					flag = false;
				break;	
			}
		}
		
		if(flag == false){
			delete v4l2;
			cout << "Not support: " << WIDTH << "," << HEIGHT << "," << _FMT << endl;
			return -1;
		}
	}

	cout << "OPT LIST" << endl;
	cout << "DEVICE: " << DEVICE << endl;
	cout << "WIDTH: " << WIDTH << endl;
	cout << "HEIGHT: " << HEIGHT << endl;
	cout << "_FMT: " << _FMT << endl;
	cout << "FMT(RGA): " << RGA_FMT << endl;
	cout << "DEBUG: " << MAN_DEBUG_CAP << endl;
	
	ManGetTime time;
	int delay = 0;
	v4l2->streamOn();
	
	ManDRM drm;
	ManDRM::buffer_object * buf = NULL;
	buf = drm.getBufSwap();
	drm.printDRMInfo();
	ManRga rga;
	ManRgaBuff src;
	ManRgaBuff dst;
	rga.SetBuff(&src,WIDTH,HEIGHT,FMT);
	rga.SetBuff(&dst,buf->width,buf->height,DRM_FMT);
	src.fd = -1;
	while(1){
		time.SetStart();
		src.buff.ptr = v4l2->getFrame(-1);
		buf = drm.getBufSwap();
		dst.fd = buf->fd;
		rga.General(&src,&dst,0,IM_SCHEDULER_RGA3_CORE0 | IM_SCHEDULER_RGA3_CORE1);
		drm.drmBuffSwap();
		if(MAN_DEBUG_CAP == true) {
			delay = time.GetEndToStart();
			cout << "[CAP] Delay time: " << delay << endl;
		}
		v4l2->putFrame(src.buff.ptr);
	}
	v4l2->streamOff();
	return 0;

}
